/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
/**
 * \file
 * \brief Protocol encoder/decoder for the MaCICtrl protocol.
 * \author Antti Maula <antti.maula@tkk.fi>
 *
 * $Id: MaCICtrlData.hpp,v 1.12 2009-05-13 07:18:17 amaula Exp $
 * 
 */
#ifndef _MACI_MACICTRLDATA_HPP_
#define _MACI_MACICTRLDATA_HPP_
#include "MaCICtrlTypes.hpp"
#include "MaCIData.hpp"
#include "common/timestamp.hpp"
#include <vector>
#include <map>

namespace MaCI {
  namespace MaCICtrl {

    /// Iterator for iterating services
    typedef std::vector<TService>::iterator TServiceArrayIterator;

    /// Type for grouping multiple services in one container.
    typedef std::vector<TService> TServiceArray;

    /// Type for grouping multiple service pointers.
    typedef std::vector<const TService *> TServicePtrArray;

    /// Type for TServiceIdentification pointer array with TService keying.
    typedef std::map<TService, const TServiceIdentification *> TServiceIdentificationPtrMap;

    /// Type for TServiceIdentification array with TService keying.
    typedef std::map<TService, TServiceIdentification> TServiceIdentificationMap;

    /** MaCICtrl protocol parser.
     * This class contains the methods for decoding/encoding a 
     * MaCICtrl message.
     */
    class CMaCICtrlData : public CMaCIData
    {
    public:
      CMaCICtrlData();
      ~CMaCICtrlData();

      // Interface for moving data around
      bool DecodeFrom(gim::binbag::CBinBag *aBinBag);
      void Reset();
      void Print(const int level) const;


      /** Set timestamp element.
       *
       */
      bool SetTimestamp(const Common::TTimestamp &aStamp);


      /** Set command element.
       *
       */
      bool SetCommand(const TCommand &aCmd);


      /** Set GroupID element.
       *
       * \deprecated This function is now obsolete, use function
       * SetDeviceGroup() instead.
       *
       */
      bool SetGroupID(const TGroupID &aId) __attribute__((deprecated));


      /** Set access informatio element.
       *
       */
      bool SetAccess(const TAccess &aAccess);
      

      /** Set Authentication element.
       *
       */
      bool SetAuthentication(const TAuthentication &aAuth);


      /** Add Service element.
       *
       */
      bool AddService(const TService &aService,
                      const TServiceIdentification &aServiceIdentification = TServiceIdentification());


      /** Add a TDeviceSubgroup element.
       *
       * This function adds the given element to container. Please
       * note that the element is queried about the real size of the
       * data to add, as its contens are dynamic.
       *
       * \see AddDeviceSubgroup(const std::string &aSubGroup)
       */
      bool SetDeviceGroup(const TDeviceGroup &aGroup);


      /** Add a TDeviceSubgroup element from std::string.
       *
       */
      bool SetDeviceGroup(const std::string &aGroup);


      /** Get pointer to TTimestamp element.
       *
       */
      const MaCI::Common::TTimestamp *GetTimestamp(void) const;
      

      /** Get pointer to TCommand element.
       *
       */
      const TCommand *GetCommand(void) const;


      /** Get pointer to TGroupID element.
       *
       * \deprecated This function is now obsolete. Use the
       * GetDeviceGroup() function instead.
       *
       */
      const TGroupID *GetGroupID(void) const;


      /** Get pointer to TAccess element.
       *
       */
      const TAccess *GetAccess(void) const;


      /** Get pointer to TAuthentication element.
       *
       */
      const TAuthentication *GetAuthentication(void) const;


      /** Get pointer to TService element by Index.
       *
       */
      const TService *GetService(const unsigned int aIndex) const;


      /** Get number of Service elements in the container.
       */
      unsigned int GetServiceCount(void) const {
        return iServicePtrArray.size();
      }


      /** Get pointer to TServiceIdentification element.
       *
       */
      const TServiceIdentification *GetServiceIdentification(const TService &aService) const;

      
      /** Return TDeviceGroup.
       *
       * This function returns Device Subgroup element by index
       * number. The First element in the array is the last element in
       * the MaCISL clause, hence calling the function with parameter
       * zero returns the lowest level name.
       */
      const TDeviceGroup *GetDeviceGroup(void) const;


      /** Return Group string by index.
       *
       * This function returns Device Subgroup element string by index
       * number. The First element in the array is the last element in
       * the MaCISL clause, hence calling the function with parameter
       * zero returns the lowest level name.
       *      
       * This function differs from the 'GetDeviceSubgroup' so that it
       * return the Subgroups as std::string.
       *
       * @param[in] aIndex Level of Subgroup to get.
       * @return                String form of requested group element. If
       *                        the element doesn't exists, empty string is 
       *                        returned.
       */
      std::string GetDeviceGroupString(void) const;

    private:
      const Common::TTimestamp *iTimestampPtr; ///< Pointer to timestamp if exists
      const TCommand *iCommandPtr; ///< Pointer to command if any.
      const TGroupID *iGroupIDPtr; ///< Pointer to GroupID structure
      const TAccess *iAccessPtr; ///< Pointer to Access structure
      const TAuthentication *iAuthenticationPtr; ///< Pointer to authentication structure.
      const TDeviceGroup *iDeviceGroupPtr; ///< Pointer to DeviceGroup.
      
      TServicePtrArray iServicePtrArray; ///< Pointer to services. 
      TServiceIdentificationPtrMap iServiceIdentificationPtrMap; ///< Pointers to ServiceIdentification, keyed by TService.
      
      CMaCICtrlData(const CMaCICtrlData &)
	: iTimestampPtr(NULL),
	  iCommandPtr(NULL),
          iGroupIDPtr(NULL),
          iAccessPtr(NULL),
          iAuthenticationPtr(NULL),
          iDeviceGroupPtr(NULL),
          iServicePtrArray(),
          iServiceIdentificationPtrMap() {}
      CMaCICtrlData &operator=(const CMaCICtrlData &) { return *this; }

    };
    
  }
}

#endif
